# coding:utf8
import requests
import redis
import json
import copy
from lxml import etree

class Spider(object):
    def __init__(self, username=None, userpwd=None):
        self.db_key = 'oa_conn'
        self.userId = username or 'admin'
        self.userPwd = userpwd or '123456'
        self.pool = redis.ConnectionPool(host='127.0.0.1', port=6379, db=0)
        self.origin_url = 'http://demo.oa8000.com/'
        self.base_url = '{}OAapp/WebObjects/OAapp.woa'.format(self.origin_url)
        self.get_data_url_post = ('{}OAapp/bfapp/buffalo/portal'
                                  'Service').format(self.origin_url)
        self.login_url_post = ('{}/wo/com.oa8000.mainapp.Main/4Wa28aXv2YgE'
                               'r8HHUysXW0/0.11').format(self.base_url)
        self.iframe_url_get = ('{}OAapp/dir20170713013507205/page/CN/'
                               'PorIndex000001415X.jsp').format(self.origin_url)
        self.rs = requests.Session()
        self.headers = {
            'User-Agent': ('Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/'
                           'MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) '
                           'Chrome/59.0.3071.115 Mobile Safari/537.36')
        }
        self.rs.headers.update({'User-Agent': self.headers['User-Agent']})
        self.login_data = {
            'userId': self.userId,
            'userPwd': self.userPwd,
            'functionName': 'LOGIN',
            'screenWidth': '320',
            'screenHeight': '553',
            '11.16': 'BLUE',
            '11.18': 'CN',
            '11.20': 'BLUE',
            'wosid': '4Wa28aXv2YgEr8HHUysXW0',
        }
        self.get_data_origin = """
            <buffalo-call>
            <method>getData</method>
            <string>web</string>
            <string>%s</string>
            <string></string>
            <string></string>
            <string></string>
            <string>admi</string>
            <string>{string1}</string>
            <string>admi</string>
            <string>BM00000330LY</string>
            <string>{string2}</string>
            </buffalo-call>
        """
        self.data_map = {
            'dbsx': {
                'name': '待办事项',
                'index': -2,
                'string1': 'newwaitTask.list',
                'string2': ('{ maxRecordCount : ["4"], msgType : ["1"], '
                            'fileType : [""], sqlId : [""], sqlStr : [""], '
                            'columnAry : ["msgTitle","sendDate","senderName"], '
                            'formatAry : ["","MM-dd",""], lengthAry : '
                            '["35","20","20"], languageType : ["CN"] }')
            },
            'gsdt': {
                'name': '公司动态',
                'index': -3,
                'string1': 'newallNews.list',
                'string2': ('{ maxRecordCount : ["4"], msgType : ["3"], '
                            'fileType : [""], sqlId : [""], sqlStr : [""], '
                            'columnAry : ["msgTitle","sendDate","senderName"], '
                            'formatAry : ["","MM-dd",""], lengthAry : '
                            '["26","20","20"], languageType : ["CN"] }')
            },
            'jqwd': {
                'name': '近期文档',
                'index': -5,
                'string1': 'newrecentFile.list',
                'string2': ('{ maxRecordCount : ["4"], msgType : [""], '
                            'fileType : ["1"], sqlId : [""], sqlStr : [""], '
                            'columnAry: ["fileName","createdTime","creatorId"],'
                            'formatAry : ["","MM-dd",""], lengthAry : '
                            '["23","20","20"], languageType : ["CN"] }')
            }
        }
        self.get_data = copy.copy(self.get_data_origin)
        self.login()
        try:
            self.test('gsdt')
        except Exception, e:
            print '登录错误，正在清除redis重新登录'
            self.del_redis_by_name(self.db_key)
            self.get_data = copy.copy(self.get_data_origin)
            self.login()

    def test(self, typename):
        self.get_data_by_name(typename)

    def del_redis_by_name(self, name):
        cor = redis.Redis(connection_pool=self.pool)
        cor.delete(name)

    def login(self):
        """获取session值并激活会话登录状态"""
        data = self.get_data_from_redis()
        if data:
            data = json.loads(data.replace('\'', '"'))
        if data and data.has_key('sessionId') and data.has_key('tokenId') \
                and data['sessionId'] and data['tokenId']:
            self.tokenId = data['tokenId']
            self.sessionId = data['sessionId']
            self.get_data = self.get_data % (self.tokenId)
            self.rs.headers.update({'JSESSIONID': self.sessionId})
        else:
            self.rs.get(self.base_url)
            self.sessionId = self.rs.cookies.get('JSESSIONID')
            self.rs.post(self.login_url_post, data=self.login_data)
            self.get_user_token()
            self.save_to_redis()

    def get_user_token(self):
        """获取用户token"""
        text = self.rs.get(self.iframe_url_get).text
        xx = etree.HTML(text)
        self.tokenId = xx.xpath('//input[@id="traceUserToken"]')[0].get('value')
        self.get_data = self.get_data % (self.tokenId)

    def save_to_redis(self):
        """将sessionid和tokenid存储到redis数据库"""
        cor = redis.Redis(connection_pool=self.pool)
        cor.hset('oa_conn', self.userId, {'sessionId': self.sessionId,
                                          'tokenId': self.tokenId})

    def get_data_from_redis(self):
        """返回sessionid和tokenid的值
           数据格式如{'sessionId': 'xxx', 'tokenId': 'xxx'}"""
        cor = redis.Redis(connection_pool=self.pool)
        print cor.hget('oa_conn', self.userId)
        return cor.hget('oa_conn', self.userId)

    def get_data_by_name(self, name):
        """作用：返回指定类别块的数据
           调用方式：self.get_data_by_name('dbsx')
           name：为data_map的各一级属性值，中文含义见其name属性
           返回数据格式：[data1, data2, ...]"""
        data = self.get_data.format(string1=self.data_map[name]['string1'],
                                    string2=self.data_map[name]['string2'])
        text = self.rs.post(self.get_data_url_post, data=data).text
        data_xml = etree.XML(text)
        maps = data_xml.xpath('//buffalo-reply/list/map')
        ans = []
        for m in maps:
            ans.append(m.xpath('string/text()')[self.data_map[name]['index']])
        return ans


if __name__ == '__main__':
    spider = Spider()
    result = spider.get_data_by_name('dbsx')
    print result
    result = spider.get_data_by_name('jqwd')
    print result
    result = spider.get_data_by_name('gsdt')
    print result
